﻿using System;
using System.Collections.Generic;
using System.Diagnostics;


namespace SoftwareArchitecture
{
    class Program
    {
        static readonly Dictionary<int, DatabaseRowStockItem> _stockItems = new Dictionary<int, DatabaseRowStockItem>();

        static readonly HashSet<int> _threeForTwo = new HashSet<int>();
        static readonly HashSet<int> _twoForOne = new HashSet<int>();
        static readonly HashSet<int> _freeDelivery = new HashSet<int>();

        static void Main(string[] args)
        {
            // add stock (Would be read in from a datatable)
            AddStock();

            // set up today's special offers. (Would be read in from a datatable)

            TodaysSpecialOffers();

            // make a purchase order
            
            TotaliseAndApplyDiscounts(AnOrder());
            TotaliseAndApplyDiscounts(AnotherOrder());

            Console.ReadLine();
        }

        private static void TotaliseAndApplyDiscounts(List<int> purchaseOrder)
        {
            Debug.WriteLine("Totalising and Applying Discounts for Order");
            Debug.WriteLine("");
            decimal total = RingUpOrder(purchaseOrder);

            Debug.WriteLine("Total " + total);
            Debug.WriteLine("");
            Debug.WriteLine("Checking for discounts...");

            decimal discount3F2 = ApplyThreeForTwoDiscounts(purchaseOrder);
            if (discount3F2 != 0)
            {
                Debug.WriteLine("");
                Debug.WriteLine("Discount 3 for 2 " + discount3F2);
            }

            decimal discount2F1 = ApplyTwoForOneDiscounts(purchaseOrder);
            if (discount2F1 != 0)
            {
                Debug.WriteLine("");
                Debug.WriteLine("Discount 2 for 1 " + discount2F1);
            }

            decimal discountFreeDelivery = ApplyFreeDelivery(purchaseOrder);
            if (discountFreeDelivery != 0)
            {
                Debug.WriteLine("");
                Debug.WriteLine("Free Delivery  " + discountFreeDelivery);
            }

            Decimal amountDue = total - (discount3F2 + discount2F1 + discountFreeDelivery);
            Debug.WriteLine("");
            Debug.WriteLine("Please pay  " + amountDue);
            Debug.WriteLine("");
            Debug.WriteLine("");
            Debug.WriteLine(".................");
        }

        static List<int> AnOrder()
        {
            var purchaseOrder = new List<int>();
            purchaseOrder.Add(1001); // scan 5 apples
            purchaseOrder.Add(1001);
            purchaseOrder.Add(1001);
            purchaseOrder.Add(1001);
            purchaseOrder.Add(1003); // scan 1 lemon
            purchaseOrder.Add(1004); // scan 1 pie
            //purchaseOrder.Add(1001); // another apple
            purchaseOrder.Add(1002); // An orange
            return purchaseOrder;
        }

        static List<int> AnotherOrder()
        {
            var purchaseOrder = new List<int>();
            purchaseOrder.Add(1004); // scan 1 pie
            purchaseOrder.Add(1004); // scan 1 pie
            purchaseOrder.Add(1004); // scan 1 pie
            purchaseOrder.Add(1004); // scan 1 pie
            purchaseOrder.Add(1004); // scan 1 pie
            purchaseOrder.Add(1004); // scan 1 pie
            purchaseOrder.Add(1004); // scan 1 pie
            purchaseOrder.Add(1004); // scan 1 pie
            purchaseOrder.Add(1004); // scan 1 pie
            purchaseOrder.Add(1004); // scan 1 pie
            return purchaseOrder;
        }
        

        private static void TodaysSpecialOffers()
        {
            _threeForTwo.Add(1001);
            _twoForOne.Add(1001);
            _freeDelivery.Add(1001);
        }

        

        private static decimal ApplyFreeDelivery(IEnumerable<int> purchaseOrder)
        {
            // hard coded discount ... Apples 3 for 2!

            // count the apples
      
            decimal totalDiscount = 0m;

            foreach (var productCode in purchaseOrder)
            {
                if (_freeDelivery.Contains(productCode))
                {
                    totalDiscount += _stockItems[productCode].Delivery;
                }
            }

            return totalDiscount;
        }

        private static decimal ApplyTwoForOneDiscounts(IEnumerable<int> purchaseOrder)
        {
            // hard coded discount ... Apples 3 for 2!

            // count the apples
            int count = 0;
            decimal totalDiscount = 0m;

            foreach (var productCode in purchaseOrder)
            {
                if (_twoForOne.Contains(productCode))
                {
                    count++;
                    if (count % 2 == 0)
                    {
                        totalDiscount += _stockItems[productCode].UnitCost;
                        totalDiscount += _stockItems[productCode].Delivery;
                    }
                }
            }

            return totalDiscount;
        }

        private static decimal ApplyThreeForTwoDiscounts(IEnumerable<int> purchaseOrder)
        {
            // hard coded discount ... Apples 3 for 2!

            // count the apples
            int count = 0;
            decimal totalDiscount = 0m;

            foreach (var productCode in purchaseOrder)
            {
                if (_threeForTwo.Contains(productCode))
                {
                    count++;
                    if (count % 3 == 0)
                    {
                        totalDiscount += _stockItems[productCode].UnitCost;
                        totalDiscount += _stockItems[productCode].Delivery;
                    }
                }
            }

            return totalDiscount;
        }

        private static void AddStock()
        {
            _stockItems.Add(1001, new DatabaseRowStockItem { Name = "Apple", UnitCost = 0.24m, Delivery = 0.10m });
            _stockItems.Add(1002, new DatabaseRowStockItem { Name = "Orange", UnitCost = 0.54m, Delivery = 0.10m });
            _stockItems.Add(1003, new DatabaseRowStockItem { Name = "Lemon", UnitCost = 0.05m, Delivery = 0.20m });
            _stockItems.Add(1004, new DatabaseRowStockItem { Name = "Sausage Pie", UnitCost = 12.49m, Delivery = 5.20m });
        }

        private static decimal RingUpOrder(List<int> purchaseOrder)
        {
            decimal total = 0m;
            foreach (var productCode in purchaseOrder)
            {
                Debug.WriteLine(_stockItems[productCode]);
                total += _stockItems[productCode].UnitCost;
                total += _stockItems[productCode].Delivery;
            }
            return total;
        }
    }
}
